package chapter3;

import chapter2.Apple;
import chapter2.version2.AppleVersionTwo;

import java.util.ArrayList;
import java.util.List;

public class TypeCheck {
    /**
     * 类型检查、类型推断以及限制
     *
     * 1、类型检查
     *      Lambda的类型是从Lambda的上下文推断出来的。
     *
     */


    public static void main(String[] args) {
        /**
         * 类型检查的例子：
         *
         * 1、看下filter的定义
         *      filter(List<Apple>inventory, Predicate<Apple>p)
         * 2、确定目标类型就是 Predicate<Apple>
         * 3、Predicate<Apple>接口的抽象方法是什么?
         * 4、抽象方法是test 它接收有个Apple类型的参数 返回值是boolean
         * 5、函数描述符Apple -> boolean匹配Lambda的签名 它接受一个Apple类型参数 返回值是boolean  因此代码类型检查无误
         */
        List<Apple> inventory = new ArrayList<>();
        List<Apple> heavierThan150g = AppleVersionTwo.filter(inventory,(Apple a) -> a.getWeight() > 150);

        /**
         * 类型推断
         *
         * 这个例子中 参数a  没有显示的类型
         */

        List<Apple> greenApples = AppleVersionTwo.filter(inventory,a -> "green".equals(a.getColor()));

        /**
         * 使用局部变量
         *  Lambda表达式 也运行使用自由变量(不是参数的 而是在外层作用域中定义的变量) 和匿名函数一样 这称为捕获Lambda
         *  注意Lambda引用的局部变量必须显式的声明为final 即Lambda 表达式只能捕获派发给它们的局部变量一次
         */
        int portNumber = 1337;
        Runnable r = () -> System.out.println(portNumber);
//        portNumber = 1449;  编译错误 引用的局部变量必须是final或事实上的final 即不能修改

    }
}
